在使用Glide的过程中,遇到不少问题,如下:
- 加载本地国际化图片资源时出现错乱。
- 加载Gif图时显示奇慢。
- Glide加载图片的ImageView不能设置tag。
- 使用CircleImageView时图片显示不正常。
本文,对遇到的这些问题进行了分析和总结。
Glide是Google的一个图片加载的优秀开源库。其几大特点:
- 通过with()参数传入Activity/Fragment,实现图片加载和Activity/Fragment的生命周期联动,即onPause即停止加载,onResume继续下载。
- 专门针对列表加载进行了优化,不用担心复用convertView引起图片错位问题的出现。
- 支持gif图,支持gif图,不用再额外添加gif的支持库。
- 图片质量。图片质量参数默认采用2bytes/pixel的Bitmap.Config.RGB_565,如果对图片质量要求高,可通过自定义GlideModule来实现4bytes/pixel高质量的ARGB_8888。
- 智能的内存开销优化。Glide每次加载都会自动计算出ImageView的大小和所需要的显示尺寸,而不是将全尺寸的图片加载至内存,优化内存占用。
- 智能的磁盘缓存,加载显示快。Picasso每次加载都是全尺寸的图片,所有在列表快速滑动时,加载速度会较慢;但是Glide可以设置磁盘缓存策略DiskCacheStrategy.ALL,即缓存全尺寸又缓存其他尺寸,使得列表中快速回滚时图片可以迅速加载显示。
- 可以直接加载本地资源图片,比直接设置src更省内存。
- 链式调用,简单到没有学习成本。
- 库体积小啊。
为啥不用其他的图片加载开源库呢?
- Fresco. 很牛逼,加载据说是最快的,但是体积太大。
- Picasso. 内存占用大,加载较慢。
- UImageLoader. 配置参数多多。
但是…..他们都不支持Gif啊,还是选我大Glide吧,而且Glide在绝大多数应用场景中已经够用和优秀。
下面就说说在项目实际使用中遇到的一些坑,和对应的解决方案,正文开始。
踩坑与填坑
Glide加载本地国际化图片资源时出现错乱
坑
为了批量加载大图片避免oom,采用Glide加载本地图片资源,但是在切换应用语言时,对应的国际化的图片资源却没自动切换。纳尼?莫非Glide不支持国际化资源加载,不可能啊,在不同语言下刚安装第一进入时加载都是正确的呀!哪个地方出问题了呢?
分析
经过分析测试,把问题定位在磁盘缓存上。Glide在不设置DiskCacheStrategy时默认采用DiskCacheStrategy.RESULT的缓存策略,即存储此次加载的结果,那么,在切换语言时,再次加载图片时,默认是从缓存中读取的,而不是新的资源路径,那么就会造成这次加载的和上次加载的一样,结果就是,切换了语言环境,但是图片资源无变化。
解决方案
只需修改其磁盘缓存策略即可,不做磁盘缓存,即设置磁盘缓存策略为NONE,代码实现为:
|
|
建议:使用Glide加载本地图片时最好将磁盘缓存策略设置为NONE,首先,既然是本地资源,根本无需再做本地缓存了,其次避免出现类似国际化资源出现的问题。
Glide加载Gif图片时显示奇慢
坑:
在利用Glide加载Gif图片时,采用和加载.png/.jpg一样的调用方式时,发现Gif图的加载速度超级慢啊,而应用中Gif图有时会有连续的好几张,这时就一直loading,真烦人。
分析:
在搜索后,准备到Glide下提个issue,发现已经有人提过,而且作者也给出了解决方案,加载Gif时除了调用asGif()方法外,还需特别设置缓存策略(又是缓存策略的问题,可见这块是个烦人的点啊),需要将缓存策略设置为SOURCE或者NONE,即设置为缓存原图资源或者不做缓存。猜想是,在做ALL或者RESULT的缓存策略时,需要转换处理Gif图,造成较耗资源,显示缓慢。
解决方案:
三点:asGIf(), DiskCacheStrategy.SOURCE/NONE, dontAnimate(), dontAnimate()为个人建议,实测中发现去掉动画会显示更快。
在实际项目中可以这样写:
|
|
Glide加载的ImageView设置tag就报错
坑:
利用Glide加载图片的ImageView,在给其设置tag时会出现报错:Java.lang.IllegalArgumentException: You must not call setTag() on a view Glide is targeting 。这是因为Glide为了防止在列表中出现的错乱情况,默认给Glide加载的对象(ImageView)设置了tag,就像我们早期使用图片加载时自己手动做的tag处理防止图片加载错位。
解决方案:
以下三种方案,参考自博文Glide 一个专注于平滑滚动的图片加载和缓存库
方案一:
最简单方便,使用setTag(int,object)方法设置tag。
方案二:
(1) 先实现GlideMoudle接口,全局设置ViewTaget的tagId
|
|
(2) 在ids.xml下添加id
|
|
(3) 在AndroidManifest.xml文件里面添加
|
|
方案三:
写一个继承自ImageViewTaget的类,复写它的get/setRequest方法。具体实现参考博文,再次不再贴出。
使用CircleImageView加载图片时显示不正常
坑:
在使用CircleImageView实现圆形头像时,如果Glide设置了placeHolder,加载时会出现加载不出图片的情况。
分析:
CircleImageView引起的与占位图和显示动画的冲突问题。
解决方案:
方案一: 不设置placeholder占位图。
方案二: 使用Glide的Transformation自己设置圆形图片,具体参考这个How do rounded image with Glide library?。
方案三: 去掉Glide加载的默认动画,即调用dontAnimate()方法。